package cn.wj.school.cloud.service;

import cn.wj.school.cloud.dao.SyResourceMapper;
import cn.wj.school.cloud.dto.PageResponse;
import cn.wj.school.cloud.dto.PrivilegeCheckDTO;
import cn.wj.school.cloud.dto.SyResourceDTO;
import cn.wj.school.cloud.dto.SyUserDTO;
import cn.wj.school.cloud.dto.condition.ResourceCondition;
import cn.wj.school.cloud.enums.OperationType;
import cn.wj.school.cloud.exception.ServiceInvokeException;
import cn.wj.school.cloud.model.SyResource;
import cn.wj.school.cloud.utils.BeanCopyUtil;
import cn.wj.school.cloud.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;

import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @Author: yueding
 * @Description: 资源实现类
 * @Date: Created in 15:20 2018/6/2
 * @Modified By: Copyright(c) cai-inc.com
 */
@Service
@Slf4j
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private SyResourceMapper resourceMapper;

    private PathMatcher matcher = new AntPathMatcher();

    /**
     * 是否有权限访问相关url
     *
     * @param user
     * @param url
     * @return
     */
    @Override
    public PrivilegeCheckDTO isResourcePermit(SyUserDTO user, String url) {
        PrivilegeCheckDTO dto = new PrivilegeCheckDTO();
        // 获取匿名访问url
        List<SyResource> resources =
                resourceMapper.selectResourceByPrivilege(PrivilegeCheckDTO.AccessType.ANONYMOUS.toNumber());
        if (!CollectionUtils.isEmpty(resources)) {
            resources.forEach(resource -> {
                if (matcher.match(resource.getUrl(), url)) {
                    dto.setIsPermit(Boolean.TRUE);
                    dto.setAccessType(PrivilegeCheckDTO.AccessType.ANONYMOUS.toNumber());
                }
                return;
            });
        }
        // 继续查询用户的权限
        if (!dto.getIsPermit() && user != null) {
            authenticateLoginUrl(url, dto);
            // 用户权限范围的
            if (!dto.getIsPermit()) {
                // TODO: 2019/1/9 权限先写死
                setLoginUserPrivilege(user, url, dto);
            }
        }
        // 如果还是没权限,设置errorType
        if (!dto.getIsPermit()) {
            dto.setAccessType(PrivilegeCheckDTO.AccessType.AUTHENTICATE.toNumber());
            if (user != null) {
                dto.setErrorType(PrivilegeCheckDTO.ErrorType.UNAUTHORIZED.toNumber());
                dto.setError(PrivilegeCheckDTO.ErrorType.UNAUTHORIZED.toName());
            } else {
                dto.setErrorType(PrivilegeCheckDTO.ErrorType.UNAUTHENTICATED.toNumber());
                dto.setError(PrivilegeCheckDTO.ErrorType.UNAUTHENTICATED.toName());
            }

        }
        return dto;
    }

    /**
     * 登录就能访问的url
     * 
     * @param url
     * @param dto
     */
    private void authenticateLoginUrl(String url, PrivilegeCheckDTO dto) {
        List<SyResource> resources;// 登录访问url
        resources = resourceMapper.selectResourceByPrivilege(PrivilegeCheckDTO.AccessType.AUTHENTICATE.toNumber());
        if (!CollectionUtils.isEmpty(resources)) {
            resources.forEach(resource -> {
                if (matcher.match(resource.getUrl(), url)) {
                    dto.setIsPermit(Boolean.TRUE);
                    dto.setAccessType(PrivilegeCheckDTO.AccessType.AUTHENTICATE.toNumber());
                }
                return;
            });
        }
    }

    /**
     * 用户授权的url
     * 
     * @param user
     * @param url
     * @param dto
     */
    private void setLoginUserPrivilege(SyUserDTO user, String url, PrivilegeCheckDTO dto) {
        /*List<SysRoleDTO> roles = roleService.getRolesByUserCode(user.getAccount());
        if (!CollectionUtils.isEmpty(roles)) {
            List<SyResource> resources = resourceMapper
                    .selectResourcesByRoles(roles.stream().map(SysRoleDTO::getRoleCode).collect(Collectors.toList()));
            resources.forEach(resource -> {
                if (matcher.match(resource.getUrl(), url)) {
                    dto.setIsPermit(Boolean.TRUE);
                    dto.setAccessType(resource.getPrivilege());
                    setPrivilegeCheckDTO(resource, user, dto);
                    return;
                }
            });
        }
        return;*/
    }

    /**
     * 设置权限dto
     *
     * @param resource
     * @param user
     * @param dto
     */
    private void setPrivilegeCheckDTO(SyResource resource, SyUserDTO user, PrivilegeCheckDTO dto) {

        // 认证访问,必须用户登录
        if (PrivilegeCheckDTO.AccessType.AUTHENTICATE.toNumber() == resource.getPrivilege().intValue()
                && user == null) {
            dto.setErrorType(PrivilegeCheckDTO.ErrorType.UNAUTHENTICATED.toNumber());
            dto.setError("用户未登录");
        }
    }

    /**
     * 分页查询资源信息
     *
     * @param condition
     * @return
     */
    @Override
    public PageResponse<SyResourceDTO> getResourcesByCondition(ResourceCondition condition) {
        long count = resourceMapper.countResourcesByCondition(condition);
        if (count > 0) {
            return new PageResponse<>(count, BeanCopyUtil
                    .genBeanList(resourceMapper.selectResourcesByCondition(condition), SyResourceDTO.class));
        }
        return new PageResponse<>(count, Collections.emptyList());
    }

    /**
     * 获取资源详情
     *
     * @param resourceId
     * @return
     */
    @Override
    public SyResourceDTO getResoureDetailById(Long resourceId) {
        if (resourceId == null) {
            throw ServiceInvokeException.newException("参数异常!");
        }

        return BeanCopyUtil.genBean(resourceMapper.selectByPrimaryKey(resourceId), SyResourceDTO.class);
    }

    /**
     * 保存resource
     *
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveResource(SyResourceDTO dto) {
        if (dto == null) {
            return;
        }
        isExitsCode(dto.getResourceCode(), null);
        SyResource resource = BeanCopyUtil.genBean(dto, SyResource.class);
        SyUserDTO user = SecurityUtils.getCurrentUser();
        resource.setCreateInfo(user.getId(), user.getUserName(), OperationType.CREATE);
        resourceMapper.insertSelective(resource);

    }

    /**
     * 修改
     *
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void modifyResource(SyResourceDTO dto) {
        if (dto == null || dto.getId() == null) {
            throw ServiceInvokeException.newException("参数异常,ID缺少!");
        }
        // 存在校验
        isExitsCode(dto.getResourceCode(), dto.getId());
        SyResource resource = BeanCopyUtil.genBean(dto, SyResource.class);
        SyUserDTO user = SecurityUtils.getCurrentUser();
        resource.setCreateInfo(user.getId(), user.getUserName(), OperationType.MODIFY);
        resourceMapper.updateByPrimaryKeySelective(resource);
    }

    /**
     * 删除
     *
     * @param resourceId
     */
    @Override
    public void removeResource(Long resourceId) {
        if (resourceId != null) {
            resourceMapper.deleteByPrimaryKey(resourceId);
        }
    }

    /**
     * code唯一性校驗
     *
     * @param resourceCode
     * @param id
     * @return
     */
    private void isExitsCode(String resourceCode, Long id) {
        List<SyResource> resources = resourceMapper.selectResourcesByCode(resourceCode);
        if (!CollectionUtils.isEmpty(resources)) {
            resources.forEach(resource -> {
                if (!resource.getId().equals(id)) {
                    throw ServiceInvokeException.newException("编号已存在");
                }
            });
        }
    }
}
